#include "cppTutorSocketServer.h"

#include "cppTutorLog.h"
extern CcppTutorLog Log;

#include <iostream>

using namespace std;

//#ifdef SOCKET_TCP
#ifdef WIN32
    // add windows specefic defenition
#else
ServerSocket :: ServerSocket ( int port )
{
#ifdef WIN32
    // add windows specefic defenition
#else
    if (!Socket::socket())
    {
        throw SocketException ( "Could not create server socket." );
    }
#endif

#ifdef WIN32
    // add windows specefic defenition
#else
    if (!Socket::bind ( port ))
    {
        throw SocketException ( "Could not bind to port." );
    }
#endif

#ifdef WIN32
    // add windows specefic defenition
#else
    if (!Socket::listen())
    {
        throw SocketException ( "Could not listen to socket." );
    }
#endif
}

ServerSocket::~ServerSocket()
{
}

const ServerSocket& ServerSocket::operator << ( const std::string& s ) const
{
#ifdef WIN32
    // add windows specefic defenition
#else
    if (!Socket::send ( s ))
    {
        throw SocketException ( "Could not write to socket." );
    }
#endif
    return *this;
}

const ServerSocket& ServerSocket::operator >> ( std::string& s ) const
{
#ifdef WIN32
    // add windows specefic defenition
#else
    if (!Socket::recv ( s ))
    {
        throw SocketException ( "Could not read from socket." );
    }
#endif
    return *this;
}

void ServerSocket::accept (ServerSocket& sock)
{
#ifdef WIN32
    // add windows specefic defenition
#else
    if (!Socket::accept (sock))
    {
        throw SocketException ( "Could not accept socket." );
    }
#endif
}
#endif //SOCKET_TCP


#ifdef SOCKET_UDP
CcppTutorSocketServer :: CcppTutorSocketServer () : sock (0), length (0), m_strPort ("999")
{
    cout << "Creating UDP Server Socket" << endl;
}

CcppTutorSocketServer :: CcppTutorSocketServer (string strPort = "") : m_strPort (strPort)
{
    cout << "Creating UDP Server Socket" << endl;
}

CcppTutorSocketServer:: ~CcppTutorSocketServer ()
{
}

void CcppTutorSocketServer :: error(const char *msg)
{
    perror(msg);
    exit(0);
}
        
int CcppTutorSocketServer :: udp_server(int argc1, char *argv1[])
{
    if (argc1 < 2) 
    {
        cout << "WARNING : No Port provided, using default port [" << m_strPort << "]" << endl;
        cout << "To use a custom Port, run the program again using : " << argv1[0] << " <port no>" << endl;
    }
    else
    {
        m_strPort = argv1[1];
        cout << "using port [" << m_strPort << "]" << endl;
    }
   
    sock=socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0) 
    {
        error("Opening socket");
    }
    else
    {
        cout << "Socket Opened : " << sock << endl;
    }
    length = sizeof(server);
#ifdef WIN32
    // add windows specefic defenition
#else
    bzero(&server,length);
#endif
    server.sin_family       =   AF_INET;
    server.sin_addr.s_addr  =   INADDR_ANY;
    server.sin_port         =   htons(atoi(m_strPort.c_str()));

    //cout << "Binding tp ip address : " << server.sin_addr.s_addr << endl;
    if (bind(sock, (struct sockaddr *)&server, length)<0) 
    {
        error("binding");
    }
    else
    {
        cout << "bind success" << endl;
    }
    
    fromlen = sizeof(struct sockaddr_in);
    while (1) 
    {
        n = recvfrom(sock,buf, 1024, 0, (struct sockaddr *)&from, &fromlen);
        if (n < 0) 
        {
            error("recvfrom");
        }
#ifdef WIN32
    // add windows specefic defenition
#else
        write(1,"Received a datagram: ",21);
        write(1,buf,n);
#endif
        n = sendto(sock,"Got your message\n", 17, 0, (struct sockaddr *)&from,fromlen);
        if (n  < 0) 
        {
            error("sendto");
        }
    }
    return 0;
}
//#endif //SOCKET_UDP
#endif
